package com.tanhua.server.service;

import com.tanhua.commons.template.AliyunOssTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.Comment;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.mongo.UserFrozen;
import com.tanhua.domain.mongo.Visitor;
import com.tanhua.domain.vo.ErrorResult;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.PublishVO;
import com.tanhua.domain.vo.VisitorVO;
import com.tanhua.dubbo.api.*;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.util.RelativeDateFormat;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class MovementsService {

    @Reference
    private PublishApi publishApi;
    @Reference
    private UserInfoApi userInfoApi;
    @Reference
    private CommentApi commentApi;
    @Reference
    private VisitorApi visitorApi;
    @Reference
    private UserFrozenApi userFrozenApi;
    @Autowired
    private AliyunOssTemplate ossTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private MovementMQService mqService;


    /**
     * 圈子推荐动态
     */
    public ResponseEntity findRecommendPublish(int page, int pagesize) {
        User user = UserHolder.getUser();
        PageResult pageResult = null;
        //先从redis查询大数据推荐的动态
        pageResult = findByRedis(page, pagesize, user.getId());
        //查询推荐给当前用户的动态列表
        if (pageResult == null || pageResult.getItems().size() == 0) {
            pageResult = publishApi.findRecommendPublish(page, pagesize, user.getId());
        }
        return ResponseEntity.ok(changePublishVO(pageResult, user));
    }

    private PageResult findByRedis(int page, int pagesize, Long userId) {
        //QUANZI_PUBLISH_RECOMMEND_1
        String strPids = redisTemplate.opsForValue().get("QUANZI_PUBLISH_RECOMMEND_" + userId);
        if (strPids == null) {
            return null;
        }

        String[] arrPids = strPids.split(",");
        int count = arrPids.length;
        int pages = (int) Math.ceil(count * 1.0 / pagesize);
        if (page > pages) {
            return null;
        }

        //分页查询起始索引
        int index = (page - 1) * pagesize;
        int end = index + pagesize;
        if (end > count) {
            end = count;
        }

        List<Long> pidList = new ArrayList<>();
        for (int i = index; i < end; i++) {
            pidList.add(Long.parseLong(arrPids[i].toString()));
        }

        List<Publish> publishList = publishApi.findListByPids(pidList);


        return new PageResult(count, pagesize, pages, page, publishList);
    }

    /**
     * 发布动态
     */
    public ResponseEntity publishMovement(MultipartFile[] imageContent, Publish publish) throws IOException {
        User user = UserHolder.getUser();
        //查询冻结状态
        UserFrozen userFrozen = userFrozenApi.findUserFrozenByUserId(user.getId());
        if (userFrozen != null && userFrozen.getFreezingRange() == 3) {
            log.info("动态发布功能已被冻结");
            return ResponseEntity.status(500).body(ErrorResult.publishFrozen(userFrozen.getOutTime()));
        }
        //1. 设置userId
        publish.setUserId(user.getId());
        //2. 上传动态图片
        List<String> medias = new ArrayList<>();
        if (imageContent != null && imageContent.length > 0) {
            for (MultipartFile file : imageContent) {
                String url = ossTemplate.upload(file.getInputStream(), file.getOriginalFilename());
                medias.add(url);
            }
        }
        publish.setMedias(medias);
        //设置初始审核状态
        publish.setState(0);

        //保存动态信息, 返回动态地
        String publishId = publishApi.save(publish);

        //发送MQ消息，用于动态审核
        rocketMQTemplate.convertAndSend("tanhua-publish", publishId);
        log.info("【发送MQ消息】topic:{}, message:{}", "tanhua-publish", publishId);

        //发送MQ消息，用于大数据推荐动态
        mqService.sendMsgWithSave(publishId);
        return ResponseEntity.ok(null);
    }

    /**
     * 好友动态
     */
    public ResponseEntity findPublishOfFriend(int page, int pagesize) {
        User user = UserHolder.getUser();
        PageResult pageResult = publishApi.findFriendPublish(page, pagesize, user.getId());
        return ResponseEntity.ok(changePublishVO(pageResult, user));
    }

    /**
     * 用户动态查询
     */
    public ResponseEntity findUserPublish(int page, int pagesize, Long userId) {
        PageResult pageResult = publishApi.findUserPublish(page, pagesize, userId);
        User user = new User();
        user.setId(userId);
        return ResponseEntity.ok(changePublishVO(pageResult, user));
    }

    /**
     * 动态点赞 commentType 1
     */
    public ResponseEntity like(String publishId) {
        User user = UserHolder.getUser();
        //查询冻结状态
        UserFrozen userFrozen = userFrozenApi.findUserFrozenByUserId(user.getId());
        if (userFrozen != null && userFrozen.getFreezingRange() == 2) {
            return ResponseEntity.status(500).body(ErrorResult.commentFrozen(userFrozen.getOutTime()));
        }
        return ResponseEntity.ok(addComment(publishId, 1));
    }

    /**
     * 动态取消点赞
     */
    public ResponseEntity dislike(String publishId) {
        User user = UserHolder.getUser();
        //查询冻结状态
        UserFrozen userFrozen = userFrozenApi.findUserFrozenByUserId(user.getId());
        if (userFrozen != null && userFrozen.getFreezingRange() == 2) {
            return ResponseEntity.status(500).body(ErrorResult.commentFrozen(userFrozen.getOutTime()));
        }
        return ResponseEntity.ok(removeComment(publishId, 1));
    }

    /**
     * 查询单条动态
     *
     * @param publishId
     * @return
     */
    public ResponseEntity findOnePublish(String publishId) {
        User user = UserHolder.getUser();
        Publish publish = publishApi.findById(new ObjectId(publishId));
        //转换vo
        PublishVO vo = new PublishVO();
        //封装发布人信息
        UserInfo userInfo = userInfoApi.findById(publish.getUserId());
        BeanUtils.copyProperties(userInfo, vo);
        if (userInfo.getTags() != null) {
            vo.setTags(userInfo.getTags().split(","));
        }
        //封装publish信息
        BeanUtils.copyProperties(publish, vo);
        //设置id
        vo.setId(publish.getId().toHexString());
        //设置imageContent
        vo.setImageContent(publish.getMedias().toArray(new String[]{}));
        //设置distance
        vo.setDistance("50米");
        vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
        boolean hasLiked = redisTemplate.hasKey("publish_like_" + user.getId() + "_" + publish.getId());
        vo.setHasLiked(hasLiked ? 1 : 0);
        vo.setHasLoved(0);
        mqService.sendMsgWithBrowse(publishId);
        return ResponseEntity.ok(vo);
    }

    /**
     * 动态喜欢 commentType 3
     *
     * @param publishId
     * @return
     */
    public ResponseEntity love(String publishId) {
        User user = UserHolder.getUser();
        //查询冻结状态
        UserFrozen userFrozen = userFrozenApi.findUserFrozenByUserId(user.getId());
        if (userFrozen != null && userFrozen.getFreezingRange() == 2) {
            return ResponseEntity.status(500).body(ErrorResult.commentFrozen(userFrozen.getOutTime()));
        }
        return ResponseEntity.ok(addComment(publishId, 3));
    }

    /**
     * 动态-取消喜欢
     *
     * @param publishId
     * @return
     */
    public ResponseEntity unLove(String publishId) {
        User user = UserHolder.getUser();
        //查询冻结状态
        UserFrozen userFrozen = userFrozenApi.findUserFrozenByUserId(user.getId());
        if (userFrozen != null && userFrozen.getFreezingRange() == 2) {
            return ResponseEntity.status(500).body(ErrorResult.commentFrozen(userFrozen.getOutTime()));
        }
        return ResponseEntity.ok(removeComment(publishId, 3));
    }

    //============================重复方法提取=================================

    /**
     * publish 转换为publishVO类
     */
    private PageResult changePublishVO(PageResult pageResult, User user) {
        List<Publish> publishList = pageResult.getItems();
        //转换成vo
        List<PublishVO> voList = new ArrayList<>();
        for (Publish publish : publishList) {
            PublishVO vo = new PublishVO();
            //封装发布人信息
            UserInfo userInfo = userInfoApi.findById(publish.getUserId());
            BeanUtils.copyProperties(userInfo, vo);
            if (userInfo.getTags() != null) {
                vo.setTags(userInfo.getTags().split(","));
            }
            //封装publish信息
            BeanUtils.copyProperties(publish, vo);
            //设置id
            vo.setId(publish.getId().toHexString());
            //设置imageContent
            vo.setImageContent(publish.getMedias().toArray(new String[]{}));
            //设置distance
            vo.setDistance("50米");
            vo.setCreateDate(RelativeDateFormat.format(new Date(publish.getCreated())));
            boolean hasLiked = redisTemplate.hasKey("publish_like_" + user.getId() + "_" + publish.getId());
            vo.setHasLiked(hasLiked ? 1 : 0);
            boolean hasLoved = redisTemplate.hasKey("publish_love_" + user.getId() + "_" + publish.getId());
            vo.setHasLoved(hasLoved ? 1 : 0);
            voList.add(vo);
        }
        pageResult.setItems(voList);
        return pageResult;
    }

    /**
     * 新增comment(点赞，喜欢)
     */
    private Integer addComment(String publishId, Integer commentType) {
        User user = UserHolder.getUser();
        //封装评论对象
        Comment comment = new Comment();
        comment.setPubType(1);
        comment.setCommentType(commentType);
        comment.setUserId(user.getId());
        comment.setPublishId(new ObjectId(publishId));
        //添加被评论人到comment
        Publish publish = publishApi.findById(new ObjectId(publishId));
        comment.setPublishUserId(publish.getUserId());

        //保存喜欢
        Integer count = commentApi.saveComment(comment);

        //当前用户喜欢记录保存到redis中
        if (commentType == 1) {
            redisTemplate.opsForValue().set("publish_like_" + user.getId() + "_" + comment.getPublishId().toHexString(), "1");
            mqService.sendMsgWithLike(publishId);
        } else if (commentType == 3) {
            redisTemplate.opsForValue().set("publish_love_" + user.getId() + "_" + comment.getPublishId().toHexString(), "1");
            mqService.sendMsgWithLove(publishId);
        }
        return count;
    }

    /**
     * 取消comment(点赞，喜欢)
     */
    private Integer removeComment(String publishId, Integer commentType) {
        User user = UserHolder.getUser();
        //封装comment对象
        Comment comment = new Comment();
        comment.setUserId(user.getId());
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(commentType);
        comment.setPubType(1);
        Integer count = commentApi.removeComment(comment);
        //并删除掉redis中的点赞记录
        if (commentType == 1) {
            redisTemplate.delete("publish_like_" + user.getId() + "_" + publishId);
            mqService.sendMsgWithDislike(publishId);
        } else if (commentType == 3) {
            redisTemplate.delete("publish_love_" + user.getId() + "_" + publishId);
            mqService.sendMsgWithUnlove(publishId);
        }
        return count;
    }

    /**
     * 查看最近访客
     */
    public ResponseEntity findVisitors() {
        Long userId = UserHolder.getUser().getId();
        //1. 先从redis中查看上一次的查看最近访客的时间
        String time = redisTemplate.opsForValue().get("visitor_time_" + userId);
        List<Visitor> visitorList = null;
        //2. 根据上次查看时间查询最新访客记录
        if (time == null) {
            //第一次查看最近访客,从数据库查询最新的五条记录
            visitorList = visitorApi.findVisitorListByCount(userId, 5);
        } else {
            //查询time之后的访问记录
            visitorList = visitorApi.findVisitorListByStartDate(userId, time);
        }
        //转换vo
        List<VisitorVO> vos = new ArrayList<>();
        for (Visitor visitor : visitorList) {
            VisitorVO vo = new VisitorVO();
            //查询访问者的信息
            UserInfo userInfo = userInfoApi.findById(visitor.getVisitorUserId());
            BeanUtils.copyProperties(userInfo, vo);
            vo.setId(userInfo.getId());
            vos.add(vo);
        }
        //注意：将此次查看最近访客时间存入redis
        redisTemplate.opsForValue().set("visitor_time_" + userId, String.valueOf(System.currentTimeMillis()));
        return ResponseEntity.ok(vos);
    }
}
